package com.qianfeng.smartplatform.security.handlers;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.qianfeng.smartplatform.cache.RoleCache;
import com.qianfeng.smartplatform.event.LoginEvent;
import com.qianfeng.smartplatform.mapper.UserRoleMapper;
import com.qianfeng.smartplatform.pojo.Menu;
import com.qianfeng.smartplatform.pojo.MyBaseUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by Jackiechan on 2022/6/6 10:21
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Component
public class MyUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {


    private UserRoleMapper userRoleMapper;


    private RoleCache roleCache;

    @Autowired
    public void setRoleCache(RoleCache roleCache) {
        this.roleCache = roleCache;
    }

    @Autowired
    public void setUserRoleMapper(UserRoleMapper userRoleMapper) {
        this.userRoleMapper = userRoleMapper;
    }

    private ApplicationContext context;

    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    /**
     * 当认证(登录)成功之后执行
     * @param request
     * @param response
     * @param authentication
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
      //  super.onAuthenticationSuccess(request, response, authentication);
        //java.lang.IllegalStateException: 提交响应后无法调用sendRedirect（）。注意不要写super,否则会提示这个错误
        response.sendRedirect("/index.html");
        MyBaseUser principal = (MyBaseUser) authentication.getPrincipal();//这个的返回值就是spring里面的user,也就是我们userdetailservice中的返回值
        //在这里才能确认用户登录成功,然后根据用户的数据获取到用户的角色,然后能获取到用户的权限,设置给用户
        Long userId = principal.getUserId();
        //根据用户的id查询到所有的角色id
        List<Long> roleIds = userRoleMapper.selectRoleIdByUserId(userId);
        //根据对应的角色id,查询到所有的角色
        //集合,用于保存用户所有权限的集合
//        List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
//        roleIds.forEach(roleId -> {
//            //根据角色的id获取到角色
//            Role role = roleCache.get(roleId);
//            //根据角色找到所有的菜单
//            List<Menu> menuList = role.getMenuList();
//            //将用户有的菜单中的权限字符串取出来,转成spring srcurity中的权限对象
//            List<SimpleGrantedAuthority> list = menuList.stream()
//                    .map(Menu::getPerms)
//                    .map(SimpleGrantedAuthority::new)
//                    .collect(Collectors.toList());
//            authorityList.addAll(list);
//        });

        List<SimpleGrantedAuthority> authorityList = roleIds.stream().flatMap(roleId -> {
                    return roleCache.get(roleId).getMenuList().stream();
                }).map(Menu::getPerms)
                //SimpleGrantedAuthority的构造方法的参数必修不能为空,为了防止null带来的问题,在这里将数据进行过滤之后在作为构造参数传递
                .filter(perms -> perms != null)
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
        //重新给当前用户设置权限
        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(principal,authentication.getCredentials(),authorityList));
        context.publishEvent(new LoginEvent(LoginEvent.LoginType.SUCCESS, principal.getUsername()));
    }
}
